package com.sushengren.easyword.anchor;

import com.sushengren.easyword.model.AnchorContext;
import org.apache.poi.xwpf.usermodel.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 占位符定位
 *
 * @author sushengren
 */
public class PlaceholderAnchor implements Anchor {

    /**
     * 占位符号
     */
    public static final String FLAG_START = "{";

    /**
     * 占位符号
     */
    public static final String FLAG_END = "}";

    /**
     * 占位符分隔符号
     */
    public static final String FLAG_SPLIT = "_";

    /**
     * 换行符
     */
    public static final String LINE_SPLIT = "\n";

    @Override
    public List<AnchorContext> locate(XWPFDocument document) {
        List<AnchorContext> result = new ArrayList<>();
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell tableCell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : tableCell.getParagraphs()) {
                        result.addAll(parse(paragraph));
                    }
                }
            }
        }
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            result.addAll(parse(paragraph));
        }

        for (int i = 0; i < result.size(); i++) {
            AnchorContext anchorContext = result.get(i);
            int cursor = i;
            while (cursor != 0) {
                cursor -= 1;
                AnchorContext before = result.get(cursor);
                if (before.getKey().equals(anchorContext.getKey())) {
                    anchorContext.setKeyIndex(anchorContext.getKeyIndex() + 1);
                }
            }
        }
        return result;
    }

    /**
     * 解析段落中的占位符
     *
     * @param paragraph 段落
     */
    private List<AnchorContext> parse(XWPFParagraph paragraph) {
        boolean read = false;
        StringBuilder key = new StringBuilder();
        List<AnchorContext> result = new ArrayList<>();
        List<XWPFRun> runList = null;
        for (XWPFRun run : paragraph.getRuns()) {
            for (String runText : run.text().split("")) {
                if (FLAG_START.equals(runText)) {
                    read = true;
                    runList = new ArrayList<>();
                }
                if (read && FLAG_END.equals(runText)) {
                    if (!runList.contains(run)) {
                        runList.add(run);
                    }
                    read = false;

                    AnchorContext anchorContext = new AnchorContext();
                    anchorContext.setKey(key.toString());
                    anchorContext.setDocument(run.getDocument());
                    anchorContext.setParagraph(run.getParagraph());
                    anchorContext.setRuns(runList);
                    anchorContext.setAnchor(this);
                    result.add(anchorContext);

                    clearPlaceholder(key.toString(), runList);
                    key.delete(0, key.length());
                }
                if (read && !runList.contains(run)) {
                    runList.add(run);
                }
                if (read && !FLAG_START.equals(runText)) {
                    key.append(runText);
                }
            }
        }
        return result;
    }

    /**
     * 清除占位符
     *
     * @param key     占位符 Key
     * @param runList 文本列表
     */
    private void clearPlaceholder(String key, List<XWPFRun> runList) {
        boolean read = false;
        for (XWPFRun run : runList) {

            // 占位符开始标识
            if (!read && run.text().contains(FLAG_START)) {
                read = true;
                run.setText(run.text().replaceFirst("\\" + FLAG_START, ""), 0);
            }

            // 占位符关键字标识
            if (read) {
                run.setText(run.text().replaceAll(FLAG_SPLIT, ""), 0);
                for (String split : key.split(FLAG_SPLIT)) {
                    run.setText(run.text().replaceFirst(split, ""), 0);
                }
            }

            // 占位符结束标识
            if (read && run.text().contains(FLAG_END)) {
                run.setText(run.text().replaceFirst(FLAG_END, ""), 0);
            }

        }
    }

}
